hvm: Clean up CR0 handling.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 27 Jul 2007 08:43:07 +0000 (09:43 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 27 Jul 2007 08:43:07 +0000 (09:43 +0100)
Upper 32 bits should #GP if set. Lower 32 bits should have reserved
bits silently cleared.

Check Intel VMX MSRs to check for compatibility with our CR0
requirements.

Signed-off-by: Eric E Liu <eric.e.liu@intel.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/vmx/vmcs.c
xen/arch/x86/hvm/vmx/vmx.c
xen/include/asm-x86/hvm/hvm.h

index e9d3d0162f7e3d2948abaf8d045f646b4d0e9c35..e7842f3e1866db44d4f0faa8eefdca81d0d598d1 100644 (file)
@@ -1668,6 +1668,17 @@ static int svm_set_cr0(unsigned long value)
   
     HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx", value);
 
+    if ( (u32)value != value )
+    {
+        HVM_DBG_LOG(DBG_LEVEL_1,
+                    "Guest attempts to set upper 32 bits in CR0: %lx",
+                    value);
+        svm_inject_exception(v, TRAP_gp_fault, 1, 0);
+        return 0;
+    }
+
+    value &= HVM_CR0_GUEST_RESERVED_BITS;
+
     /* ET is reserved and should be always be 1. */
     value |= X86_CR0_ET;
 
index 17d3724bc8b8e5b895b0f56dcb2e8f0a0cfe2ae9..d4001b70ba4aa0fed0fe0190ca369ea290ff7eb7 100644 (file)
@@ -240,9 +240,24 @@ int vmx_cpu_up(void)
 {
     u32 eax, edx;
     int cpu = smp_processor_id();
+    u64 cr0, vmx_cr0_fixed0, vmx_cr0_fixed1;
 
     BUG_ON(!(read_cr4() & X86_CR4_VMXE));
 
+    /* 
+     * Ensure the current processor operating mode meets 
+     * the requred CRO fixed bits in VMX operation. 
+     */
+    cr0 = read_cr0();
+    rdmsrl(MSR_IA32_VMX_CR0_FIXED0, vmx_cr0_fixed0);
+    rdmsrl(MSR_IA32_VMX_CR0_FIXED1, vmx_cr0_fixed1);
+    if ( (~cr0 & vmx_cr0_fixed0) || (cr0 & ~vmx_cr0_fixed1) )
+    {
+        printk("CPU%d: some settings of host CR0 are " 
+               "not allowed in VMX operation.\n", cpu);
+        return 0;
+    }
+
     rdmsr(IA32_FEATURE_CONTROL_MSR, eax, edx);
 
     if ( eax & IA32_FEATURE_CONTROL_MSR_LOCK )
index 928c4faff12013e50382bbcdbae35f1213659ae9..9aea14cfd041f84196d21368927c0008b7ab3131 100644 (file)
@@ -2200,6 +2200,17 @@ static int vmx_set_cr0(unsigned long value)
 
     HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx", value);
 
+    if ( (u32)value != value )
+    {
+        HVM_DBG_LOG(DBG_LEVEL_1,
+                    "Guest attempts to set upper 32 bits in CR0: %lx",
+                    value);
+        vmx_inject_hw_exception(v, TRAP_gp_fault, 0);
+        return 0;
+    }
+
+    value &= HVM_CR0_GUEST_RESERVED_BITS;
+
     /* ET is reserved and should be always be 1. */
     value |= X86_CR0_ET;
 
index 275a5b52c062293c13faf55cb359b6a63e66f45e..30884f58a3881cc5634fd61aa9e38fe47820e3cd 100644 (file)
@@ -300,6 +300,13 @@ static inline int hvm_event_injection_faulted(struct vcpu *v)
     return hvm_funcs.event_injection_faulted(v);
 }
 
+/* These reserved bits in lower 32 remain 0 after any load of CR0 */
+#define HVM_CR0_GUEST_RESERVED_BITS \
+    ~(X86_CR0_PE | X86_CR0_MP | X86_CR0_EM | \
+      X86_CR0_TS | X86_CR0_ET | X86_CR0_NE | \
+      X86_CR0_WP | X86_CR0_AM | X86_CR0_NW | \
+      X86_CR0_CD | X86_CR0_PG)
+
 /* These bits in CR4 are owned by the host. */
 #define HVM_CR4_HOST_MASK (mmu_cr4_features & \
     (X86_CR4_VMXE | X86_CR4_PAE | X86_CR4_MCE))